#include <iostream>
#include <unistd.h>
#include <cassert>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "ProcessPool.chh"

#define NUM 5//任务进程个数


class fifo
{
public:
    fifo(std::string str, pid_t id, int fd)
    :FILENAME(str.c_str())
    ,workerid(id)
    ,ctrlfd(fd)
    { }
    
public:
    const char *FILENAME;
    pid_t workerid;
    int ctrlfd;
};

int Work()
{
    int code = 0;
    while(true)
    {
        ssize_t n = read(0, &code, sizeof(code));
        std::cout << "read size:" << n << std::endl;
        if(n == 0)
        {
            std::cout << "write quit, mee to!" << std::endl;
            break;
        }
        else if(n > 0)
        {
            init.RunTask(code);
        }
        else
        {
            std::cerr << "errno: " << errno << "errstring: " << strerror(errno) << std::endl;
            return 1;
        }
    }
    return 0;
}

bool Createrfifo(std::vector<fifo> *fifos)
{
    std::vector<int> old;
    for(int i = 1; i <= NUM; i++)
    {
        std::string filename = "fifo-" + std::to_string(i);
        int s = mkfifo(filename.c_str(), 0644);
        if(s == -1)
        { 
            std::cout << "errno:" << errno << " strerror" << strerror(errno) << std::endl;
            return false;
        }

        pid_t id = fork();
        if(id == 0)//child
        {
            if(!old.empty())
            {
                for(auto& fd : old)
                    close(fd);
            }
            int rfd = open(filename.c_str(), O_RDONLY);
            dup2(rfd, 0);
            Work();
            std::cout << "read close!!!!!!!!!!!!!!!!!!!!!" << std::endl;
            close(rfd);
            exit(0);
        }

        //parent
        int wfd = open(filename.c_str(), O_WRONLY);
        fifos->push_back(fifo(filename, id, wfd));
        old.push_back(wfd);
    }
    return true;
}

void SendCommit(const std::vector<fifo> &fifos, int flag, int num)
{
    int pos = 0;
    while(true)
    {
        // 1. 选择任务
        int code = init.SelectTask();
        if(init.CheckSafe(code))
        {
            //2. 发送任务码
            write(fifos[pos].ctrlfd, &code, sizeof(code));
            pos = (pos + 1) % fifos.size();
        }
        // 3.判断是否退出
        if(!flag)
        {
            if(--num == 0)
            {
                break;
            }
        }
    }
    std::cout << "write finish!!!" << std::endl;
}

void Releasefifo(std::vector<fifo> &fifos)
{
    std::cout << "start release" << std::endl;
    for(auto& fifo : fifos)
    {
        std::cout << "colse wfd: " <<  fifo.ctrlfd << std::endl;
        close(fifo.ctrlfd);
        pid_t id = waitpid(fifo.workerid, nullptr, 0);
    }
    std::cout << "release success!" << std::endl;
}

int main()
{
    std::vector<fifo> fifos;
    // 1.创建命名管道，进程
    if(!Createrfifo(&fifos))
        return 0;
    sleep(2);
    for(const auto& fifo : fifos)
        std::cout << fifo.FILENAME <<":" << fifo.workerid << ":" << fifo.ctrlfd << std::endl;

    // 2.发送任务
    sleep(2);
    bool g_always_loop = true;
    SendCommit(fifos, !g_always_loop, 10);

    // 3. 回收资源
    sleep(2);
    Releasefifo(fifos);
    return 0;
}